//class TicketSaleThread extends Thread {
//    private static int ticket = 100;
//
//    public void run() { //直接锁这里，肯定不行，会导致，只有一个窗口卖票
//        while (ticket > 0) {
//            saleOneTicket();
//        }
//    }
//
//    public synchronized static void saleOneTicket() { //锁对象是TicketSaleThread类的Class对象，而一个类的Class对象在内存中肯定只有一个
//        if (ticket > 0) { //不加条件，相当于条件判断没有进入锁管控，线程安全问题就没有解决
//            System.out.println(Thread.currentThread().getName() + "卖出一张票，票号:" + ticket);
//            ticket--;
//        }
//    }
//}
//
//public class Test9 {
//    public static void main(String[] args) {
//        TicketSaleThread t1 = new TicketSaleThread();
//        TicketSaleThread t2 = new TicketSaleThread();
//        TicketSaleThread t3 = new TicketSaleThread();
//
//        t1.setName("窗口1");
//        t2.setName("窗口2");
//        t3.setName("窗口3");
//
//        t1.start();
//        t2.start();
//        t3.start();
//    }
//}

//public class Test9 {
//    public static void main(String[] args) {
//        TicketSaleRunnable tr = new TicketSaleRunnable();
//        Thread t1 = new Thread(tr, "窗口一");
//        Thread t2 = new Thread(tr, "窗口二");
//        Thread t3 = new Thread(tr, "窗口三");
//
//        t1.start();
//        t2.start();
//        t3.start();
//    }
//}
//
//class TicketSaleRunnable implements Runnable {
//    private int ticket = 100;
//
//    public void run() {//直接锁这里，肯定不行，会导致，只有一个窗口卖票
//        while (ticket > 0) {
//            saleOneTicket();
//        }
//    }
//
//    public synchronized void saleOneTicket() { //锁对象是this，这里就是TicketSaleRunnable对象，因为上面3个线程使用同一个TicketSaleRunnable对象，所以可以
//        if (ticket > 0) { //不加条件，相当于条件判断没有进入锁管控，线程安全问题就没有解决
//            System.out.println(Thread.currentThread().getName() + "卖出一张票，票号:" + ticket);
//            ticket--;
//        }
//    }
//}

public class Test9 {
    public static void main(String[] args) {
        // 2、创建资源对象
        Ticket ticket = new Ticket();

        // 3、启动多个线程操作资源类的对象
        Thread t1 = new Thread("窗口一") {
            public void run() { // 不能给 run() 直接加锁，因为t1,t2,t3的三个 run 方法分别属于三个 Thread 类对象，
                // run 方法是非静态方法，那么锁对象默认选 this，那么锁对象根本不是同一个 所以需要我们自己指定锁对象
                while (true) {
                    synchronized (ticket) {
                        ticket.sale();
                    }
                }
            }
        };

        Thread t2 = new Thread("窗口二") {
            public void run() {
                while (true) {
                    synchronized (ticket) {
                        ticket.sale();
                    }
                }
            }
        };
        Thread t3 = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    synchronized (ticket) {
                        ticket.sale();
                    }
                }
            }
        }, "窗口三");


        t1.start();
        t2.start();
        t3.start();
    }
}

// 1、编写资源类
class Ticket {
    private int ticket = 1000;

    public void sale() {//也可以直接给这个方法加锁，锁对象是this，这里就是Ticket对象
        if (ticket > 0) {
            System.out.println(Thread.currentThread().getName() + "卖出一张票，票号:" + ticket);
            ticket--;
        } else {
            throw new RuntimeException("没有票了");
        }
    }

    public int getTicket() {
        return ticket;
    }
}
